<template>
  <a-drawer
    v-model:open="visible"
    class="custom-class"
    root-class-name="root-class-name"
    :root-style="{ color: 'blue' }"
    style="color: red"
    :title="`自定义Mock方法 < ${editApiInfo?.name} >`"
    placement="bottom"
    :height="560"
  >
    <div class="flex flex-row h-full">
      <div class="flex-1 w-0">
        <codemirror
          v-model="editApiInfo.mockMethodContent"
          placeholder="请输入..."
          style="width: 100%; height: 100%; font-size: 16px"
          :autofocus="true"
          :indent-with-tab="false"
          :tab-size="2"
          :extensions="[linter(esLint(customLinter, esLintConfig)), lintGutter(), basicSetup, javascript(), oneDark]"
          @ready="onCodemirroReady"
          :phrases="chinesePhrases"
        />
      </div>
      <div class="flex-shrink-0 pl-3 flex flex-col">
        <div class="flex-1 h-0">
          <dl>
            <dt>全局变量/方法</dt>
            <dd class="cursor-pointer text-black" title="用于模拟流文件下载">mockResp.fileDownload(type,fileName)</dd>
            <dd class="cursor-pointer text-black" title="用于模拟慢接口">mockResp.delay(3000)</dd>
            <dd class="cursor-pointer text-black" title="修改http响应状态码">mockResp.sendHttpStatus(400,text)</dd>
            <dd class="cursor-pointer text-black" title="返回响应数据">mockResp.sendJson(obj)</dd>
            <dd class="cursor-pointer text-black" title="该对象包含当前请求数据">mockReq</dd>
            <dd class="cursor-pointer text-black" title="就是Mockjs的那个Mock对象">Mock</dd>
          </dl>
          <dl>
            <dt>帮助</dt>
            <dd
              class="cursor-pointer text-black"
              @click="() => onNewDocWin('mock-js', 'mock js帮助文档', 'mock-js.html')"
            >
              mockjs语法
            </dd>
          </dl>
          <dl>
            <dt>快速插入</dt>
            <dd class="cursor-pointer text-black" @click="() => onQuickInsert('mockPageResult')">模拟分页结果</dd>
            <dd class="cursor-pointer text-black" @click="() => onQuickInsert('mockNormalResult')">模拟正常响应</dd>
            <dd class="cursor-pointer text-black" @click="() => onQuickInsert('mockBizException')">模拟业务异常</dd>
            <dd class="cursor-pointer text-black" @click="() => onQuickInsert('mockHttp500')">模拟 http 500</dd>
            <dd class="cursor-pointer text-black" @click="() => onQuickInsert('mockFileDownload')">流文件下载</dd>
            <dd class="cursor-pointer text-black" @click="() => onQuickInsert('mockFileDownloadException')">
              流文件下载异常
            </dd>
            <dd class="cursor-pointer text-black" @click="() => onQuickInsert('getReqParams')">获取请求参数</dd>
            <dd class="cursor-pointer text-black" @click="() => onQuickInsert('mockSlowResp')">模拟慢接口</dd>
          </dl>
        </div>
        <div class="flex-shrink-0 flex flex-row">
          <div class="flex-shrink-0 pr-2">
            <a-button block @click="formatCode">代码格式化</a-button>
          </div>
          <div class="flex-1 w-0">
            <a-button type="primary" block @click="onSave">保存</a-button>
          </div>
        </div>
      </div>
    </div>
  </a-drawer>
</template>

<script setup lang="ts">
import { cloneDeep } from 'lodash-unified'
import { Codemirror } from 'vue-codemirror'
import { javascript, esLint } from '@codemirror/lang-javascript'
import { linter, lintGutter } from '@codemirror/lint'
import { oneDark } from '@codemirror/theme-one-dark'
import type { EditorView } from 'codemirror'
import { modify } from '@render/service/FrontApiService'
import { basicSetup } from 'codemirror'
import Linter from 'eslint4b-prebuilt'
import beautify from 'js-beautify'
import { message } from 'ant-design-vue'

const customLinter = new Linter()
const esLintConfig = {
  env: {
    es6: true,
  },
  globals: {
    Mock: 'readonly',
    mockResp: 'readonly',
    mockReq: 'readonly',
  },
}
const $emits = defineEmits<{
  methodContentSaveSuc: [apiInfo: ApiInfo]
}>()
const visible = ref(false)
const editApiInfo = ref<ApiInfo>()

const chinesePhrases = {
  // @codemirror/view
  'Control character': '控制符',
  // @codemirror/commands
  'Selection deleted': '选中删除',
  // @codemirror/language
  'Folded lines': '已折叠行',
  'Unfolded lines': '已展开行',
  to: '到',
  'folded code': '已折叠代码',
  unfold: '展开',
  'Fold line': '折叠行',
  'Unfold line': '展开行',
  // @codemirror/search
  'Go to line': '去这一行',
  go: '执行',
  Find: '查找',
  Replace: '替换',
  next: '下一个',
  previous: '上一个',
  all: '所有',
  'match case': '匹配(区分大小写)',
  'by word': '完全匹配',
  replace: '替换',
  'replace all': '替换所有',
  close: '关闭',
  'current match': '当前匹配项',
  'replaced $ matches': '$ 已替换匹配项目',
  'replaced match on line $': '已替换这一行的匹配项目 $',
  'on line': '这一行',
  // @codemirror/autocomplete
  Completions: '完成',
  // @codemirror/lint
  Diagnostics: '诊断',
  'No diagnostics': '无诊断',
}
function openDrawer(apiInfo: ApiInfo) {
  visible.value = true
  editApiInfo.value = cloneDeep(apiInfo)
}
const codeMirroView = shallowRef<EditorView>()
function onCodemirroReady({ view }: { view: EditorView }) {
  codeMirroView.value = view
}
async function formatCode() {
  const docContent = codeMirroView.value.state.doc.toString()
  const formatted = beautify(docContent, {
    indent_size: 2, //缩进两个空格
    space_in_empty_paren: true,
  })
  const tr = codeMirroView.value.state.update({
    changes: { from: 0, to: codeMirroView.value.state.doc.length, insert: formatted },
  })
  codeMirroView.value.dispatch(tr)
}
type QuickInsertType =
  | 'mockPageResult'
  | 'mockNormalResult'
  | 'mockBizException'
  | 'mockHttp500'
  | 'mockFileDownload'
  | 'mockFileDownloadException'
  | 'getReqParams'
  | 'mockSlowResp'
async function onQuickInsert(qucikInsertType: QuickInsertType) {
  if (!codeMirroView.value) return

  const code = await window.electron.getQuickInsertMockCode(qucikInsertType)
  codeMirroView.value.dispatch(codeMirroView.value.state.replaceSelection(code))
  codeMirroView.value.focus()
}

async function onSave() {
  await modify(editApiInfo.value)
  $emits('methodContentSaveSuc', editApiInfo.value)
  message.success('操作成功')
  // visible.value = false
}

function onNewDocWin(flag: string, title: string, docFileName: string) {
  window.electron.newDocWin(flag, title, docFileName)
}
defineExpose({ openDrawer })
</script>

<style scoped></style>
